﻿namespace caedisi
{
    using System.Windows.Controls;
    using System.Windows.Navigation;
    using caedisi.Views;
    using caedisi.Models;
    using caedisi.Views.Controls;
    using caedisi.Helpers;
    using caedisi.Web.DataModel;
    using System.ComponentModel;
    using caedisi.Controller;
    using System;
    using caedisi.Common;
    using System.Windows.Data;
    using System.Windows;
    using System.Threading;
    using System.Windows.Threading;
    using System.Linq;
    using System.Collections.Generic;
    using System.Windows.Input;
    using System.Collections.ObjectModel;
    using System.IO;
    using System.Windows.Media.Imaging;

    /// <summary>
    /// Home page for the application.
    /// </summary>
    public partial class Home : Page, INotifyPropertyChanged
    {
        int subdivision = 0;
        StackPanel st = new StackPanel();
        CellularAutomata ca = new CellularAutomata();
        
        int indicator = 1;
        List<CellularAutomata> listOfCa = new List<CellularAutomata>();
        List<TextBox> textB = new List<TextBox>();
        
        //bool decompose = false;

        //save cells states of current CA
        int[, ,] cellStateTypeArray = new int[50, 50, 1];
        CellularAutomata cellular = new CellularAutomata();

        //height of CA parts after partitioning
        short[] tabX = new short[50];
        //width of CA parts after partitioning
        short[] tabY = new short[50];
        //test & validate partitioning
        int[,] matrixTest = new int[50, 50];

        //x coordinates from partitioning
        short[] tX;
        //y coordinates from partitioning
        short[] tY;

        //width & height of current CA
        short width;
        short height;

        string states;
        //string statesDescription;
        List<int[, ,]> listOfRecordedState;
        bool recordedLastState = false;
        

        private object locker = new object();

        private CellularAutomata _CurrentCellularAutomata;
        /// <summary>
        /// Gets or sets the current cellular automata.
        /// </summary>
        /// <value>
        /// The current cellular automata.
        /// </value>
        public CellularAutomata CurrentCellularAutomata
        {
            get
            {
                return _CurrentCellularAutomata;
            }
            set
            {
                if (_CurrentCellularAutomata != value)
                {
                    _CurrentCellularAutomata = value;
                    this.RaisePropertyChanged("CurrentCellularAutomata");

                    OnCurrentCellularAutomataChanged(value);
                }
            }
        }

        private void OnCurrentCellularAutomataChanged(CellularAutomata value)
        {
            this.CurrentSimulation = new Simulation(ca, tX, tY, subdivision, listOfCa, indicator);
        }


        private Simulation _CurrentSimulation;
        /// <summary>
        /// Gets or sets the current simulation.
        /// </summary>
        /// <value>
        /// The current simulation.
        /// </value>
        public Simulation CurrentSimulation
        {
            get
            {
                return _CurrentSimulation;
            }
            set
            {
                if (_CurrentSimulation != value)
                {
                    _CurrentSimulation = value;
                    this.RaisePropertyChanged("CurrentSimulation");

                }
            }
        }



        private RecordState _CurrentState;
        /// <summary>
        /// Gets or sets the current state.
        /// </summary>
        /// <value>
        /// The current state.
        /// </value>
        public RecordState CurrentState
        {
            get
            {
                return _CurrentState;
            }
            set
            {
                if (_CurrentState != value)
                {
                    _CurrentState = value;
                    this.RaisePropertyChanged("CurrentState");
                }
            }
        }

        /// <summary>
        /// Creates a new <see cref="Home"/> instance.
        /// </summary>
        public Home()
        {
            InitializeComponent();

            this.Title = ApplicationStrings.HomePageTitle;
        }


        /// <summary>
        /// Executes when the user navigates to this page.
        /// </summary>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            //if (CellularAutomataController.Instance.CurrentEntity != null)
            //{
            //    this.CurrentCellularAutomata = CellularAutomataController.Instance.CurrentEntity;
            //    this.CurrentCellularAutomata.CellularAutomataAsArray = new Cell[this.CurrentCellularAutomata.Height, this.CurrentCellularAutomata.Width, 1];
            //    EntityHelper.SetCellularAutomataHierarchy(this.CurrentCellularAutomata, EnumCellStateType.Contaminated);
            //    UIHelper.ConstructGridCellularAutomataUI(this.GridCellularAutomata, this.CurrentCellularAutomata.CellularAutomataAsArray, Globals.cellularAutomataGridMode_ColumnWidth, Globals.cellularAutomataGridMode_RowHeight);                           
            //}
        }


        private bool _IsButtonBackEnabled = true;
        /// <summary>
        /// Gets or sets the is parameter enabled.
        /// </summary>
        /// <value>
        /// The is parameter enabled.
        /// </value>
        public bool IsButtonBackEnabled
        {
            get
            {
                return _IsButtonBackEnabled;
            }
            set
            {
                if (_IsButtonBackEnabled != value)
                {
                    _IsButtonBackEnabled = value;
                    this.RaisePropertyChanged("IsButtonBackEnabled");

                }
            }
        }

        private bool _IsParametersEnabled = false;
        /// <summary>
        /// Gets or sets the is parameter enabled.
        /// </summary>
        /// <value>
        /// The is parameter enabled.
        /// </value>
        public bool IsParametersEnabled
        {
            get
            {
                return _IsParametersEnabled;
            }
            set
            {
                if (_IsParametersEnabled != value)
                {
                    _IsParametersEnabled = value;
                    this.RaisePropertyChanged("IsParametersEnabled");

                }
            }
        }

        private bool _IsRecordEnabled = false;
        /// <summary>
        /// Gets or sets the is parameter enabled.
        /// </summary>
        /// <value>
        /// The is parameter enabled.
        /// </value>
        public bool IsRecordEnabled
        {
            get
            {
                return _IsRecordEnabled;
            }
            set
            {
                if (_IsRecordEnabled != value)
                {
                    _IsRecordEnabled = value;
                    this.RaisePropertyChanged("IsRecordEnabled");

                }
            }
        }
        

        private string _IsParametersVisible = "Visible";
        /// <summary>
        /// Gets or sets the is grid splitter visible.
        /// </summary>
        /// <value>
        /// The is grid splitter visible.
        /// </value>
        public string IsParametersVisible
        {
            get
            {
                return _IsParametersVisible;
            }
            set
            {
                if (_IsParametersVisible != value)
                {
                    _IsParametersVisible = value;
                    this.RaisePropertyChanged("IsParametersVisible");

                }
            }
        }


        private string _IsGridSplitterSimulationVisible = "Visible";
        /// <summary>
        /// Gets or sets the is grid splitter visible.
        /// </summary>
        /// <value>
        /// The is grid splitter visible.
        /// </value>
        public string IsGridSplitterSimulationVisible
        {
            get
            {
                return _IsGridSplitterSimulationVisible;
            }
            set
            {
                if (_IsGridSplitterSimulationVisible != value)
                {
                    _IsGridSplitterSimulationVisible = value;
                    this.RaisePropertyChanged("IsGridSplitterSimulationVisible");

                }
            }
        }
            
            
        private string _IsGridSplitterVisible = "Collapsed";
        /// <summary>
        /// Gets or sets the is grid splitter visible.
        /// </summary>
        /// <value>
        /// The is grid splitter visible.
        /// </value>
        public string IsGridSplitterVisible
        {
            get
            {
                return _IsGridSplitterVisible;
            }
            set
            {
                if (_IsGridSplitterVisible != value)
                {
                    _IsGridSplitterVisible = value;
                    this.RaisePropertyChanged("IsGridSplitterVisible");

                }
            }
        }

        private bool _IsGridSplitterEnabled = false;
        /// <summary>
        /// Gets or sets the is grid splitter enabled.
        /// </summary>
        /// <value>
        /// The is grid splitter enabled.
        /// </value>
        public bool IsGridSplitterEnabled
        {
            get
            {
                return _IsGridSplitterEnabled;
            }
            set
            {
                if (_IsGridSplitterEnabled != value)
                {
                    _IsGridSplitterEnabled = value;
                    this.RaisePropertyChanged("IsGridSplitterEnabled");

                }
            }
        }


        private string _IsThisVisible = "Collapsed";
        /// <summary>
        /// Gets or sets the is this visible.
        /// </summary>
        /// <value>
        /// The is this visible.
        /// </value>
        public string IsThisVisible
        {
            get
            {
                return _IsThisVisible;
            }
            set
            {
                if (_IsThisVisible != value)
                {
                    _IsThisVisible = value;
                    this.RaisePropertyChanged("IsThisVisible");

                }
            }
        }


        private string _IsSubdividingVisible = "Collapsed";
        /// <summary>
        /// Gets or sets the is this visible.
        /// </summary>
        /// <value>
        /// The is this visible.
        /// </value>
        public string IsSubdividingVisible
        {
            get
            {
                return _IsSubdividingVisible;
            }
            set
            {
                if (_IsSubdividingVisible != value)
                {
                    _IsSubdividingVisible = value;
                    this.RaisePropertyChanged("IsSubdividingVisible");

                }
            }
        }


        private string _IsSubdividingButtonVisible = "Collapsed";
        /// <summary>
        /// Gets or sets the is this visible.
        /// </summary>
        /// <value>
        /// The is this visible.
        /// </value>
        public string IsSubdividingButtonVisible
        {
            get
            {
                return _IsSubdividingButtonVisible;
            }
            set
            {
                if (_IsSubdividingButtonVisible != value)
                {
                    _IsSubdividingButtonVisible = value;
                    this.RaisePropertyChanged("IsSubdividingButtonVisible");

                }
            }
        }
        

        /// <summary>
        /// Handles the Click event of the ButtonOpen control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonOpen_Click(object sender, RoutedEventArgs e)
        {
            this.IsRecordEnabled = true;
            this.IsSubdividingButtonVisible = "Collapsed";
            
            this.CurrentState = new RecordState();
            this.IsSubdividingVisible = "collapsed";
            this.IsGridSplitterSimulationVisible = "Visible";
            states = "";
            this.IsParametersEnabled = true;
            this.IsThisVisible = "Collapsed";
            this.IsGridSplitterVisible = "Collapsed";

            //listOfCa = new List<CellularAutomata>();
            this.GridCellularAutomata.Children.Clear();
            CellularAutomataSearchFilter searchFilterWindow = new CellularAutomataSearchFilter();
            searchFilterWindow.Show();
            Grid grid = new Grid();
            searchFilterWindow.Closed += new EventHandler(
                (o, ev) =>
                {
                    if (searchFilterWindow.DialogResult == true)
                    {
                        
                        //cellular = this.CurrentCellularAutomata;
                        CellularAutomataController.Instance.Load(searchFilterWindow.SelectedCellularAutomataId,
                            existingCellularAutomata =>
                            {
                                this.CurrentCellularAutomata = existingCellularAutomata;

                                //directly create a simulation
                                this.CurrentSimulation = new Simulation(this.CurrentCellularAutomata);

                                //set the UI data structure
                                int numberOfRows = this.CurrentCellularAutomata.Height;
                                int numberOfColumns = this.CurrentCellularAutomata.Width;
                                this.CurrentCellularAutomata.CellularAutomataAsArray = null;
                                this.CurrentCellularAutomata.CellularAutomataAsArray = new Cell[numberOfRows, numberOfColumns, 1];
                                foreach (Cell cell in this.CurrentCellularAutomata.Cells)
                                {
                                    if (cell.x < numberOfRows && cell.y < numberOfColumns && cell.z < 1) //we need this test because the user might have increase/decrease the size of the cellular automata during simulation
                                        this.CurrentCellularAutomata.CellularAutomataAsArray[cell.x, cell.y, cell.z] = cell;
                                }
                                this.CurrentState.CellularAutomataId = existingCellularAutomata.CellularAutomataId;
                                this.CurrentState.CellularAutomataName = this.CurrentCellularAutomata.Name;
                                
                                RecordStateController.Instance.CurrentEntity = this.CurrentState;

                                //construct grid UI
                                UIHelper.ConstructGridCellularAutomataUI(grid, this.CurrentCellularAutomata.CellularAutomataAsArray, Globals.cellularAutomataGridMode_ColumnWidth, Globals.cellularAutomataGridMode_RowHeight);

                                    if (this.CurrentCellularAutomata == existingCellularAutomata)
                                    {
                                        this.IsSubdividingButtonVisible = "Visible";
                                        this.IsGridSplitterVisible = "Visible";
                                        this.IsGridSplitterEnabled = true;
                                        this.IsThisVisible = "Visible";
                                    }
                            });
            
                        this.GridCellularAutomata.Children.Add(grid);
                        
                    }
                }
                );

        }

        private void Refresh_Click(object sender, RoutedEventArgs e)
        {
            Grid grid = new Grid();
            foreach (Cell cell in this.CurrentCellularAutomata.Cells)
            {
                this.CurrentCellularAutomata.Cells.Remove(cell);
                CellularAutomataController.Instance.Context.Cells.Remove(cell);
            }
            this.OnCurrentCellularAutomataChanged(this.CurrentCellularAutomata);
            this.CurrentCellularAutomata.CellularAutomataAsArray = new Cell[this.CurrentCellularAutomata.Height, this.CurrentCellularAutomata.Width, 1];
            EntityHelper.SetCellularAutomataHierarchy(this.CurrentCellularAutomata, EnumCellStateType.Contaminated);
            UIHelper.ConstructGridCellularAutomataUI(grid, this.CurrentCellularAutomata.CellularAutomataAsArray, Globals.cellularAutomataGridMode_ColumnWidth, Globals.cellularAutomataGridMode_RowHeight);
            this.GridCellularAutomata.Children.Add(grid);
        }


        /// <summary>
        /// Handles the Click event of the ButtonVEditCAParameters control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonEditCAParameters_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            //if (!decompose)
            //{
                //show the New Cellular Parameters Window
                CellularAutomataParameters editExistingCellularAutomataParametersWindow = new CellularAutomataParameters(this.CurrentCellularAutomata, Common.EnumCellularAutomataParametersEditMode.Edit);
                editExistingCellularAutomataParametersWindow.Show();
                editExistingCellularAutomataParametersWindow.Closed += new System.EventHandler(EditExistingCellularAutomataParametersWindow_Closed);
            //}
            //else
            //{
            //    CellularAutomataParameters editExistingCellularAutomataParametersWindow = new CellularAutomataParameters(listCa[index], Common.EnumCellularAutomataParametersEditMode.Edit);
            //    editExistingCellularAutomataParametersWindow.Show();
            //    editExistingCellularAutomataParametersWindow.Closed += new System.EventHandler(EditExistingCellularAutomataParametersWindow_Closed);
            //}
        }

        /// <summary>
        /// Handles the Closed event of the EditExistingCellularAutomataParametersWindow control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        void EditExistingCellularAutomataParametersWindow_Closed(object sender, System.EventArgs e)
        {
            ;
        }


        ///// <summary>
        ///// Handles the MouseRightButtonDown event of the newVertex control.
        ///// </summary>
        ///// <param name="sender">The source of the event.</param>
        ///// <param name="e">The <see cref="System.Windows.Input.MouseButtonEventArgs"/> instance containing the event data.</param>
        //void newVertex_MouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        //{
        //   VertexControl vertexControl = sender as VertexControl;

        //   BindingExpression bindingExpression = vertexControl.GetBindingExpression(VertexControl.SelectedCellStateTypeIdEntityProperty);
        //   Cell cell = bindingExpression.DataItem as Cell;

        //   VertexProperties vertexPropertiesWindow = new VertexProperties(cell);                        
        //   vertexPropertiesWindow.Show();
        //}


        /// <summary>
        /// Handles the Click event of the ButtonPlay control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonPlay_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            recordedLastState = false;
            this.CurrentSimulation.ExecutionStatus = EnumSimulationExecutionStatus.Play;

            DispatcherTimer dispatcherTimer = new DispatcherTimer();
            dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
            dispatcherTimer.Tick += new EventHandler(
                (o, args) =>
                {
                    if (StopConditionMet())
                        dispatcherTimer.Stop();
                    else
                    {
                        setCACellsStatesToString(this.CurrentCellularAutomata.Height, this.CurrentCellularAutomata.Width);
                        states += ",";
                        this.CurrentSimulation.CurrentStep += 1;
                    }
                }
                );
            dispatcherTimer.Interval = new TimeSpan(0, 0, 1);
            dispatcherTimer.Start();
        }


        /// <summary>
        /// Stops the condition met.
        /// </summary>
        /// <returns></returns>
        private bool StopConditionMet()
        {
            bool result = false;

            if (this.CurrentSimulation.ExecutionStatus == EnumSimulationExecutionStatus.Pause)
                result = true;
            else
            {
                switch (this.CurrentSimulation.EnumConditionEndOfSimulation)
                {
                    case EnumConditionEndOfSimulation.NumberOfStepsIsReached:
                        if (this.CurrentSimulation.CurrentStep >= this.CurrentSimulation.SimulationEndConditionNumberOfSteps)
                            result = true;
                        break;

                    case EnumConditionEndOfSimulation.StateIsReached:
                        result = true;
                        foreach (Cell cell in this.CurrentCellularAutomata.Cells)
                        {
                            if (cell.CellStateTypeId != this.CurrentSimulation.SimulationEndConditionCellStateTypeId)
                            {
                                result = false;
                                break;
                            }
                        }
                        break;

                    case EnumConditionEndOfSimulation.Infinite:
                        break;

                    default:
                        break;
                }
            }

            return result;
        }

        /// <summary>
        /// Handles the Click event of the ButtonFirstStep control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonFirstStep_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            recordedLastState = false;
            states = "";
            this.CurrentSimulation.CurrentStep = 0;
            this.CurrentState.States = states;
        }


        /// <summary>
        /// Handles the Click event of the ButtonPreviousStep control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonPreviousStep_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            recordedLastState = false;
            if (this.CurrentSimulation.CurrentStep == 0)
                return;
            
            string[] tabStates = states.Split(',');
            states = "";
            int length = tabStates.Length;
            for (int i = 0; i < length - 1; i++)
            {
                states += tabStates[i] + ",";
            }
            this.CurrentSimulation.CurrentStep -= 1;
            this.CurrentState.States = states;

        }

        /// <summary>
        /// Handles the Click event of the ButtonNextStep control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonNextStep_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            recordedLastState = false;
            //this.TabControlCellularAutomataAndSimulationInfo.SelectedIndex = 1;
            
                setCACellsStatesToString(this.CurrentCellularAutomata.Height, this.CurrentCellularAutomata.Width);
                states += ",";
                        
            this.CurrentSimulation.CurrentStep += 1;
            this.CurrentState.States = states;;
        }

        /// <summary>
        /// Handles the Click event of the ButtonLastStep control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonLastStep_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            if (this.radioButtonEndSimulationInfinite.IsChecked == true)
            {
                MessageBox.Show("Please choose a valid end of simulation instead of infinite");
                return;
            }

            if (this.CurrentSimulation != null)
            {
                this.CurrentSimulation.ExecutionStatus = EnumSimulationExecutionStatus.Play;
                while (!StopConditionMet())
                    this.CurrentSimulation.CurrentStep += 1;
                setCACellsStatesToString(this.CurrentCellularAutomata.Height, this.CurrentCellularAutomata.Width);
                states += ",";
                
            }
        }

        /// <summary>
        /// Handles the Click event of the ButtonPause control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonPause_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            lock (locker)
                this.CurrentSimulation.ExecutionStatus = EnumSimulationExecutionStatus.Pause;
        }

        /// <summary>
        /// Handles the Click event of the ButtonResetAllCellState control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonResetAllCellState_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            recordedLastState = false;
            if (this.CurrentCellularAutomata == null)
            {
                MessageBox.Show("Please create or open an existing Cellular Automata first.");
            }
            else if (this.BasicCellControlResetState.SelectedCellStateTypeId == null)
            {
                MessageBox.Show("Please select a state first.");
            }
            else
            {
                foreach (Cell cell in this.CurrentCellularAutomata.Cells)
                    cell.CellStateTypeId = this.BasicCellControlResetState.SelectedCellStateTypeId.Value;
            }
        }

        /// <summary>
        /// Handles the Click event of the ButtonSave control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonSave_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            if (CellularAutomataController.Instance.HasChanges)
            {
                MessageBoxResult result = MessageBox.Show("Do you really wanna perform the save?", "Confirm Saving Cellular Automata", MessageBoxButton.OKCancel);
                if (result == MessageBoxResult.OK)
                {
                    CellularAutomataController.Instance.Save(
                        (sucess, exception) =>
                        {
                            if (sucess)
                            {
                                MessageBox.Show("Your change has been saved.");
                                this.NavigationService.Refresh();
                            }
                            else
                            {
                                MessageBox.Show("Error happened when saving the data. Exception is below" + Environment.NewLine + exception.ToString());
                            }
                        }
                    );
                }
            }
            else
            {
                MessageBox.Show("There is nothing save");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        /// <summary>
        /// Raises the property changed.
        /// </summary>
        /// <param name="propertyName">Name of the property.</param>
        protected virtual void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        /// <summary>
        /// Handles the Checked event of the radioButtonEndSimulationAllStates control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void radioButtonEndSimulationAllStates_Checked(object sender, RoutedEventArgs e)
        {
            if (this.CurrentSimulation != null)
                this.CurrentSimulation.EnumConditionEndOfSimulation = EnumConditionEndOfSimulation.StateIsReached;
        }

        /// <summary>
        /// Handles the Checked event of the radioButtonEndSimulationAfterNumberOfSteps control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void radioButtonEndSimulationAfterNumberOfSteps_Checked(object sender, RoutedEventArgs e)
        {
            if (this.CurrentSimulation != null)
                this.CurrentSimulation.EnumConditionEndOfSimulation = EnumConditionEndOfSimulation.NumberOfStepsIsReached;
        }

        /// <summary>
        /// Handles the Checked event of the radioButtonEndSimulationInfinite control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void radioButtonEndSimulationInfinite_Checked(object sender, RoutedEventArgs e)
        {
            if (this.CurrentSimulation != null)
                this.CurrentSimulation.EnumConditionEndOfSimulation = EnumConditionEndOfSimulation.Infinite;
        }

        private void ButtonNewCellularAutomata_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            this.IsRecordEnabled = false;
            this.CurrentState = new RecordState();
            this.IsSubdividingVisible = "collapsed";
            this.IsSubdividingButtonVisible = "Collapsed";
            this.IsGridSplitterSimulationVisible = "Visible";
            states = "";
            this.IsParametersEnabled = true;
            this.IsThisVisible = "Collapsed";
            this.IsGridSplitterVisible = "Collapsed";

            //listOfCa = new List<CellularAutomata>();
            Grid grid = new Grid();
            this.GridCellularAutomata.Children.Clear();
            //decompose = false;

            this.CurrentCellularAutomata = new CellularAutomata()
            {
                Width = Globals.Instance.DefaultNewCellularAutomataWidth,
                Height = Globals.Instance.DefaultNewCellularAutomataHeight,
                ImmunityTime = Globals.Instance.DefaultImmunityTime,
                RadiusContamination = Globals.Instance.DefaultRadiusContamination,
                RadiusVisibility = Globals.Instance.DefaultRadiusVisibility

            };
            this.CurrentCellularAutomata.CellularAutomataAsArray = new Cell[this.CurrentCellularAutomata.Height, this.CurrentCellularAutomata.Width, 1];
            this.CurrentSimulation = new Simulation(this.CurrentCellularAutomata);
            CellularAutomataController.Instance.CurrentEntity = this.CurrentCellularAutomata;
            this.CurrentState.CellularAutomataId = this.CurrentCellularAutomata.CellularAutomataId;
            this.CurrentState.CellularAutomataName = this.CurrentCellularAutomata.Name;
            RecordStateController.Instance.CurrentEntity = this.CurrentState;

            //show the New Cellular Parameters Window
            CellularAutomataParameters newCellularAutomataParameters = new CellularAutomataParameters(this.CurrentCellularAutomata, Common.EnumCellularAutomataParametersEditMode.New);
            newCellularAutomataParameters.Show();

            newCellularAutomataParameters.Closed += new System.EventHandler(
                (s, ev) =>

                {
                        //this.CurrentCellularAutomata = newCellularAutomataParameters.CurrentCellularAutomata;

                        if (newCellularAutomataParameters.DialogResult.Value == true)
                        {
                            //try
                            //{
                                if (this.CurrentCellularAutomata != null)
                                {
                                    this.IsSubdividingButtonVisible = "Visible";
                                    this.IsGridSplitterVisible = "Visible";
                                    this.IsGridSplitterEnabled = true;
                                    this.IsThisVisible = "Visible";
                                }
                                ////create the cellular hierarchy data
                                //if (this.EditMode == EnumCellularAutomataParametersEditMode.New)
                                EntityHelper.SetCellularAutomataHierarchy(this.CurrentCellularAutomata, EnumCellStateType.Contaminated);
                                UIHelper.ConstructGridCellularAutomataUI(grid, this.CurrentCellularAutomata.CellularAutomataAsArray, Globals.cellularAutomataGridMode_ColumnWidth, Globals.cellularAutomataGridMode_RowHeight);

                                //if (CellularAutomataController.Instance.HasChanges)
                                //{
                                //    CellularAutomataController.Instance.Save(
                                //        (sucess, exception) =>
                                //        {
                                //            this.NavigationService.Refresh();
                                //        }
                                //    );

                                //}

                            //}
                            //catch (Exception)
                            //{}

                        }

                        
                    
                }
                );

            this.GridCellularAutomata.Children.Add(grid);
        }
        

        
        /// <summary>
        /// Get height or width
        /// </summary>
        /// <param name="a"></param>
        /// <param name="b"></param>
        /// <returns></returns>
        public short calcul(short a, short b)
        {
            return (short)(b - a + 1);
        }

        /// <summary>
        /// Handles the Click event of the ButtonRecordStep control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void RecordStep_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            if (!recordedLastState)
            {
                setCACellsStatesToString(this.CurrentCellularAutomata.Height, this.CurrentCellularAutomata.Width);
                recordedLastState = true;
                this.CurrentState.States = states;
                states += ',';
            }

            
                //if (CellularAutomataController.Instance.HasChanges)
                //{
                //    MessageBoxResult result = MessageBox.Show("Do you really wanna perform the save?", "Confirm Saving Cellular Automata", MessageBoxButton.OKCancel);
                //    if (result == MessageBoxResult.OK)
                //    {
                //        CellularAutomataController.Instance.Save(
                //            (sucess, exception) =>
                //            {
                //                if (sucess)
                //                {
                //                    MessageBox.Show("Your change has been saved.");
                //                }
                //                else
                //                {
                //                    MessageBox.Show("Error happened when saving the data. Exception is below" + Environment.NewLine + exception.ToString());
                //                    return;
                //                }
                //            }
                //        );
                //    }
                //}
                //else
                //{
                //    MessageBox.Show("There is nothing save");
                //}



                AddDescription addDescription = new AddDescription();
                addDescription.Show();
                addDescription.Closed += new System.EventHandler(
                    (s, ev) =>
                    {
                        //this.CurrentCellularAutomata = newCellularAutomataParameters.CurrentCellularAutomata;
                        if (addDescription.DialogResult.Value == true)
                        {
                            this.CurrentState.RecordDescription = addDescription.Description.Text;

                            if (RecordStateController.Instance.HasChanges)
                            {
                                MessageBoxResult result = MessageBox.Show("Do you really wanna perform the save?", "Confirm Saving States", MessageBoxButton.OKCancel);
                                if (result == MessageBoxResult.OK)
                                    RecordStateController.Instance.Save(
                                       (sucess, exception) =>
                                       {
                                           if (sucess)
                                               MessageBox.Show("Your change has been saved.");
                                           else
                                           {
                                               MessageBox.Show("Error happened when saving the data. Exception is below" + Environment.NewLine + exception.ToString());
                                           }
                                       }
                                   );
                            }

                            else
                            {
                                MessageBox.Show("There is nothing save");
                            }


                        }
                    }
                    );
            

        }


        /// <summary>
        /// Transform the string state to table
        /// </summary>
        /// <param name="ch"></param>
        /// <returns></returns>
        public string[] GetCACellsStatesTab(string ch)
        {
            string[] tabStates = ch.Split(',');
            return tabStates;
        }

        
        /// <summary>
        /// Get the state list of all steps
        /// </summary>
        /// <param name="ch"></param>
        /// <param name="height"></param>
        /// <param name="width"></param>
        public void setListRecorded(string ch, short height, short width)
        {
            int y;
            int k = 0;
            string[] tabCh = GetCACellsStatesTab(ch);
            for (int index = 0; index < tabCh.Length; index++)
            {
                int[, ,] recordedState = new int[30, 30, 1];

                int l = 0;

                string chh = tabCh[k];
                k++;
                char[] b = new char[chh.Length];
                for (int i = 0; i < height; i++)
                {
                    for (int j = 0; j < width; j++)
                    {

                        using (StringReader sr = new StringReader(chh))
                        {
                            // Read 1 characters from the string into the array.
                            sr.Read(b, 0, b.Length);
                        }
                        y = int.Parse(b[l].ToString());

                        recordedState[i, j, 0] = y;
                        l++;
                    }
                }
                listOfRecordedState.Add(recordedState);
            }
        }

        /// <summary>
        /// Get the current state of a CA
        /// </summary>
        /// <param name="height"></param>
        /// <param name="width"></param>
        public void setCACellsStatesToString(short height, short width)
        {
            for (int i = 0; i < height; i++)
            {
                for (int j = 0; j < width; j++)
                {
                    int k = 0;
                    states += this.CurrentCellularAutomata.CellularAutomataAsArray[i, j, k].CellStateTypeId;

                }
            }
        }



        /// <summary>
        /// Handles the Click event of the ButtonShowRecorded control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ButtonShowRecorded_Click(object sender, System.Windows.RoutedEventArgs e)
        {
            IsGridSplitterVisible = "Collapsed";
            this.IsGridSplitterSimulationVisible = "Collapsed";
            IsThisVisible = "Collapsed";

            listOfRecordedState = new List<int[, ,]>();
            this.GridCellularAutomata.Children.Clear();
            
            StackPanel stack = new StackPanel();
            stack.Orientation = Orientation.Horizontal;
            stack.VerticalAlignment = VerticalAlignment.Center;
            stack.HorizontalAlignment = HorizontalAlignment.Center;

            ShowRecordedStates showRecordedStatesWindow = new ShowRecordedStates();
            showRecordedStatesWindow.Show();


            showRecordedStatesWindow.Closed += new EventHandler(
                (o, ev) =>
                {
                    if (showRecordedStatesWindow.DialogResult == true)
                    {

                        RecordStateController.Instance.Load(showRecordedStatesWindow.SelectedRecordId,
                            existingRecordState =>
                            {
                                CellularAutomataController.Instance.Load(existingRecordState.CellularAutomataId,
                            existingCellularAutomata =>
                            {
                                this.CurrentCellularAutomata = existingCellularAutomata;

                                //*************************
                                width = existingCellularAutomata.Width;
                                height = existingCellularAutomata.Height;
                                setListRecorded(existingRecordState.States, height, width);

                                int index = 0;
                                foreach (int[, ,] statesMatrix in listOfRecordedState)
                                {
                                    Grid g = new Grid();

                                    //Create RightArrow
                                    Image myImage = new Image();
                                    BitmapImage bi = new BitmapImage();
                                    bi.UriSource = new Uri("/caedisi;component/Assets/Images/RightArrow-icon.png", UriKind.Relative);
                                    myImage.Source = bi;
                                    myImage.Height = 20;
                                    myImage.Width = 30;

                                    if (index != 0)
                                        stack.Children.Add(myImage);
                                    stack.Children.Add(g);

                                    CellularAutomata t = existingCellularAutomata;
                                    t = new CellularAutomata()
                                    {
                                        Width = width,
                                        Height = height,
                                        ImmunityTime = Globals.Instance.DefaultImmunityTime,
                                        RadiusContamination = Globals.Instance.DefaultRadiusContamination,
                                        RadiusVisibility = Globals.Instance.DefaultRadiusVisibility,
                                    };
                                    t.CellularAutomataAsArray = new Cell[t.Height, t.Width, 1];
                                    t.NeighbourhoodTypeId = existingCellularAutomata.NeighbourhoodTypeId;
                                    CellularAutomataController.Instance.CurrentEntity = t;

                                    ////create the cellular hierarchy data
                                    //if (this.EditMode == EnumCellularAutomataParametersEditMode.New)
                                    EntityHelper.SetCellularAutomataHierarchyForPartition(t, statesMatrix);
                                    UIHelper.ConstructGridRecordedCellularAutomataUI(g, t.CellularAutomataAsArray, Globals.cellularAutomataGridMode_ColumnWidth, Globals.cellularAutomataGridMode_RowHeight);
                                    index++;

                                }
                            });
                            });
                        this.GridCellularAutomata.Children.Add(stack);

                    }
                }
        );

        }

        /// <summary>
        /// Flag for subdivision
        /// </summary>
        private void triTXTY()
        {
            short aux;
            for (int o = 0; o < tX.Length; o += 2)
            {
                if (tX[o] < tX[o + 1])
                {
                    if (tY[o] > tY[o + 1])
                    {
                        aux = tY[o];
                        tY[o] = tY[o + 1];
                        tY[o + 1] = aux;
                    }
                }
                else
                {
                    if (tY[o] > tY[o + 1])
                    {
                        aux = tX[o];
                        tX[o] = tX[o + 1];
                        tX[o + 1] = aux;

                        aux = tY[o];
                        tY[o] = tY[o + 1];
                        tY[o + 1] = aux;

                    }
                    else
                    {
                        aux = tX[o];
                        tX[o] = tX[o + 1];
                        tX[o + 1] = aux;
                    }
                }
            }

        }

        /// <summary>
        /// Send parameters of subdivision to begin the simulation
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Subdivide_Click(object sender, RoutedEventArgs e)
        {
            subdivision = 1;
            
            triTXTY();
            this.OnCurrentCellularAutomataChanged(this.CurrentCellularAutomata);
            this.IsSubdividingVisible = "Collapsed"; 
        }

        /// <summary>
        /// Activate the menu of partition and start subdivision
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SetGridVisible_Click(object sender, RoutedEventArgs e)
        {
            Grid grid = new Grid();
            ca = this.CurrentCellularAutomata;
            tX = new short[30];
            tY = new short[30];
            
            UIHelper.SetRep(1);
            UIHelper.ConstructGridSubdividedCellularAutomata(listOfCa, this.GridPartition, this.GridSimulationInfo, grid, this.CurrentCellularAutomata.CellularAutomataAsArray, Globals.cellularAutomataGridMode_ColumnWidth, Globals.cellularAutomataGridMode_RowHeight, tX, tY, ca, this.IsParametersVisible);
            this.CurrentSimulation.CurrentStep = 0;
            this.IsSubdividingVisible = "Visible";
            this.GridCellularAutomata.Children.Add(grid);
            
        }

        /// <summary>
        /// Hide the menu of partition and return to the basic mode of execution
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SetGridInvisible_Click(object sender, RoutedEventArgs e)
        {
            Grid grid = new Grid();
            tX = new short[30];
            tY = new short[30];
            
            UIHelper.SetRep(0);
            UIHelper.ConstructGridSubdividedCellularAutomata(listOfCa, this.GridPartition, this.GridSimulationInfo, grid, this.CurrentCellularAutomata.CellularAutomataAsArray, Globals.cellularAutomataGridMode_ColumnWidth, Globals.cellularAutomataGridMode_RowHeight, tX, tY, this.CurrentCellularAutomata, this.IsParametersVisible);
            
            this.GridCellularAutomata.Children.Add(grid);
            this.IsSubdividingVisible = "Collapsed";
        }

        /// <summary>
        /// Cancel the current partition
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ButtonBack_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                UIHelper.backButton(tX, tY);
            }
            catch (Exception)
            {
                MessageBox.Show("No partition available");
            }
        }


        //private void ButtonBascule_Click(object sender, SelectionChangedEventArgs e)
        //{
        //    UIHelper.ConstructGridCellularAutomataUI(this.GridCellularAutomata, this.CurrentCellularAutomata.CellularAutomataAsArray, Globals.cellularAutomataGridMode_ColumnWidth, Globals.cellularAutomataGridMode_RowHeight);
        //}

    }
}